﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using CRL.Data;
using CRL.Data.Attribute;
using CRL.Data.DBAccess;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CRL.EFCore.Extensions
{
    public static class Extensions
    {
        static bool init = false;
        public static void UseExtensions(this DbContextOptionsBuilder builder)
        {
            if (init)
            {
                return;
            }
            SettingConfig.StringFieldLength = 50;
            SettingConfig.CheckModelTableMaping = false;
            SettingConfig.CompileSp = false;
            SettingConfig.UpdateModelCache = false;
            var configBuilder = DBConfigRegister.GetInstance() as DBConfigRegister;
            //var pro = dBAccessBuild._connection.GetType().GetProperty("DbProviderFactory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            //var dbFactory = (DbProviderFactory)pro.GetValue(dBAccessBuild._connection);
            configBuilder.RegisterDBType(DBType.MSSQL, (dBAccessBuild) =>
            {
                return new DblHelper(null, dBAccessBuild);
            }, (context) =>
            {
                return new MSSQLDBAdapter2(context);
            });
            //configBuilder.RegisterDBType(DBType.MYSQL, (dBAccessBuild) =>
            //{
            //    return new DblHelper(null, dBAccessBuild);
            //}, (context) =>
            //{
            //    return new MySql.MySQLDBAdapter(context);
            //});
            //configBuilder.RegisterDBType(DBType.SQLITE, (dBAccessBuild) =>
            //{
            //    return new DblHelper(null, dBAccessBuild);
            //}, (context) =>
            //{
            //    return new Sqlite.SqliteDBAdapter(context);
            //});
            init = true;
        }
        /// <summary>
        /// 配置实体结构以支持表结构维护
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="builder"></param>
        public static void ConfigEntityTypeBuilder<T>(this EntityTypeBuilder<T> builder) where T : class
        {
            var tableInfo = TypeCache.GetTable(typeof(T));
            tableInfo.TableName = typeof(T).Name;
            var entityType = builder.Metadata as Annotatable;
            var table = entityType.FindAnnotation("Relational:TableName");
            if (table != null)
            {
                tableInfo.TableName = table.Value.ToString();
            }
            var pros = builder.Metadata.GetProperties();
            var unionIndexs = new List<Index>();
            foreach (Property item in pros)
            {
                var a = tableInfo.FieldsDic.TryGetValue(item.Name, out var f);
                if (!a)
                {
                    continue;
                }
                f.MapingName = item["Relational:ColumnName"]?.ToString() ?? f.MemberName;
                f.ColumnType = item["Relational:ColumnType"]?.ToString() ?? "";
                if (item["MaxLength"] != null)
                {
                    f.Length = (int)item["MaxLength"];
                }
                if (item.IsPrimaryKey())
                {
                    var idGenerate = item.PropertyInfo.GetCustomAttribute<System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute>();
                    f.KeepIdentity = true;
                    var isNumber = item.PropertyInfo.PropertyType == typeof(int) || item.PropertyInfo.PropertyType == typeof(long);
                    if (idGenerate != null)
                    {
                        f.KeepIdentity = idGenerate.DatabaseGeneratedOption == System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None;
                    }
                    else if (isNumber)
                    {
                        f.KeepIdentity = false;
                    }
                    f.IsPrimaryKey = true;
                    tableInfo.PrimaryKey = f;
                }
                if (item.IsIndex())
                {
                    var index = item.Indexes.First();
                    var isUnique = index.IsUnique;
                    if (index.Properties.Count == 1)
                    {
                        f.FieldIndexType = isUnique ? FieldIndexType.非聚集唯一 : FieldIndexType.非聚集;
                    }
                    else
                    {
                        unionIndexs.Add(index);
                    }
                }
            }
            foreach (var index in unionIndexs)//unionIndexs
            {
                var isUnique = index.IsUnique;
                var fields = new List<string>();
                foreach (var p in index.Properties)
                {
                    tableInfo.FieldsDic.TryGetValue(p.Name, out var f);
                    fields.Add(f.MapingName);
                }
                var indexName = string.Join("_", index.Properties.Select(b => b.Name));
                AbsPropertyBuilder.SetUnionIndex<T>(indexName, fields, isUnique ? FieldIndexType.非聚集唯一 : FieldIndexType.非聚集);
            }
        }
    }
}
